Estaba haciendo algunos ejercicios de codificación y terminé usando un set de frozenset s. Aquí está el código:
cities = 4 roads = [[0, 1], [1, 2], [2, 0]] roads = set([frozenset(road) for road in roads]) output = [] for i in range(cities-1): for j in range(i+1, cities): if set([i,j]) not in roads: output.append([i,j]) Como puede ver, el if en el for anidado prueba la presencia del conjunto en el conjunto de conjuntos. Sin embargo, entendí que en este caso, los hashables deben usarse con el operador in .
Si reemplazo set([i,j]) con [i,j] , obtengo el siguiente error:
TypeError: unhashable type: 'list'Entonces, aquí está mi pregunta: ¿por qué funciona con el conjunto, que no es (hasta donde yo sé) hashable y no con la lista? ¿No debería arrojar también un error, qué me estoy perdiendo?
No importa, encontré la respuesta en la documentación , para cualquiera que se pregunte:
Tenga en cuenta que el argumento elem para los __contains__() , remove() y discard() puede ser un conjunto. Para admitir la búsqueda de un conjunto congelado equivalente, se crea uno temporal a partir de elem.
Según mi lectura de la fuente de CPython, parece que la prueba contains controles si la clave se encuentra en el conjunto; si no, y si la clave es un objeto set , se intenta convertir la clave en un conjunto frozenset y luego se prueba esa clave. El mismo comportamiento existe para operaciones como remove , como se ve aquí:
>>> s = set([frozenset([1,2])]) >>> s {frozenset({1, 2})} >>> s.remove(set([1,2])) >>> s set() El código en cuestión en el intérprete es la función set_contains() en Objects/setobject.c .